#include "line_detect.h"

void line_detecter::detect_lines_try(cv::Mat &img_to_line)
{
    cv::cvtColor(img_to_line,img_to_line,CV_BGR2GRAY);

    cv::Mat binary;
    cv::Mat morphologyEx1;
    cv::Mat morphologyEx2;
    cv::Mat cannyimg;

    //cv::threshold(img_to_line,binary,127,255,cv::THRESH_BINARY_INV|cv::THRESH_OTSU);
    cv::inRange(img_to_line, cv::Scalar(0, 0, 211), cv::Scalar(180, 30, 255),binary);

    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));//创建结构元素大小为3*3

    cv::morphologyEx(binary,        morphologyEx1, cv::MORPH_CLOSE, kernel);//开操作
    cv::morphologyEx(morphologyEx1, morphologyEx2, cv::MORPH_OPEN,  kernel);

    cv::Canny(morphologyEx2, cannyimg, 50, 150);
    //imwrite("binary.jpg",binary);
    //imwrite("morphologyEx1.jpg",morphologyEx1);
    //imwrite("morphologyEx2.jpg",morphologyEx2);
    //imwrite("cannyimg.jpg",cannyimg);

    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(cannyimg,lines,1,CV_PI/180.0,40,50,10);

    std::vector<cv::Vec4i>  filtered;
    std::vector<cv::Vec4i>  filtered_o1;
    std::vector<cv::Vec4i>  filtered_o2;
    std::vector<cv::Vec4i>  filtered_o3;
    for(int i = 0;i<lines.size();i++)
    {
        cv::Vec4i templine = lines[i];
        if(templine[1] == templine[3])
        {
            filtered.push_back(templine);
            if(templine[1] >2000)
            {
                filtered_o1.push_back(templine);
            }else if(templine[1] >1000 && templine[1]<2000)
            {
                filtered_o2.push_back(templine);
            }else{
                filtered_o3.push_back(templine);
            }
        }
    }

     cv::Mat result=img_to_line.clone();
     for(int i=0;i<filtered.size();i++)
     {
         cv::Vec4i lin=filtered[i];

         cv::line(result,cv::Point(lin[0],lin[1]),cv::Point(lin[2],lin[3]),
         cv::Scalar(0,0,255),2,8,0);
     }
    imwrite("result.jpg",result);
    //lines = cv2.HoughLinesP(edges, 1, np.pi / 180, 40,minLineLength=10,maxLineGap=10)

    int i,j,k,n;
    std::cout<<"\nEnter the no. of data pairs to be entered:\n";        //To find the size of arrays
    //cin>>n;
    n = filtered_o1.size();
    double x[n],y[n],a,b;
    std::cout<<"\nEnter the x-axis values:\n";                //Input x-values
    for (i=0;i<n;i++)
        x[i] = filtered_o1[i][0];
    std::cout<<"\nEnter the y-axis values:\n";                //Input y-values
    for (i=0;i<n;i++)
        y[i] = filtered_o1[i][1];
    double xsum=0,x2sum=0,ysum=0,xysum=0;                //variables for sums/sigma of xi,yi,xi^2,xiyi etc
    for (i=0;i<n;i++)
    {
        xsum=xsum+x[i];                        //calculate sigma(xi)
        ysum=ysum+y[i];                        //calculate sigma(yi)
        x2sum=x2sum+pow(x[i],2);                //calculate sigma(x^2i)
        xysum=xysum+x[i]*y[i];                    //calculate sigma(xi*yi)
    }
    a=(n*xysum-xsum*ysum)/(n*x2sum-xsum*xsum);            //calculate slope
    b=(x2sum*ysum-xsum*xysum)/(x2sum*n-xsum*xsum);            //calculate intercept
    double y_fit[n];                        //an array to store the new fitted values of y    
    for (i=0;i<n;i++)
        y_fit[i]=a*x[i]+b;                    //to calculate y(fitted) at given x points
    std::cout<<"S.no"<<std::setw(5)<<"x"<<std::setw(19)<<"y(observed)"<<std::setw(19)<<"y(fitted)"<<std::endl;
    std::cout<<"-----------------------------------------------------------------\n";
    for (i=0;i<n;i++)
        std::cout<<i+1<<"."<<std::setw(8)<<x[i]<<std::setw(15)<<y[i]<<std::setw(18)<<y_fit[i]<<std::endl;//print a table of x,y(obs.) and y(fit.)    
    std::cout<<"\nThe linear fit line is of the form:\n\n"<<a<<"x + "<<b<<std::endl; 



}

std::vector<cv::Vec4i> line_detecter::detect_lines(cv::Mat &img_to_line)
{
    if(img_to_line.channels()!=1)
    {
        cv::cvtColor(img_to_line,img_to_line,CV_BGR2GRAY);
    }

    cv::Mat binary;
    cv::Mat morphologyEx1;
    cv::Mat morphologyEx2;
    cv::Mat cannyimg;

    //cv::threshold(img_to_line,binary,127,255,cv::THRESH_BINARY_INV|cv::THRESH_OTSU);
    cv::inRange(img_to_line, cv::Scalar(0, 0, 211), cv::Scalar(180, 30, 255),binary);

    cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT,cv::Size(3,3));//创建结构元素大小为3*3

    cv::morphologyEx(binary,        morphologyEx1, cv::MORPH_CLOSE, kernel);//开操作
    cv::morphologyEx(morphologyEx1, morphologyEx2, cv::MORPH_OPEN,  kernel);

    cv::Canny(morphologyEx2, cannyimg, 50, 150);

    std::vector<cv::Vec4i> lines;
    cv::HoughLinesP(cannyimg,lines,1,CV_PI/180.0,40,50,10);

    return lines;
}

void line_detecter::lines_to_line(std::vector<cv::Vec4i>  & lines, float & y1 ,float & y2)
{
    std::vector<cv::Vec4i>  filtered;
    std::vector<cv::Vec4i>  filtered_o1;
    float filtered_o1_k;
    float filtered_o1_b;
    std::vector<cv::Vec4i>  filtered_o2;
    float filtered_o2_k;
    float filtered_o2_b;
    std::vector<cv::Vec4i>  filtered_o3;
    float filtered_o3_k;
    float filtered_o3_b;
    for(int i = 0;i<lines.size();i++)
    {
        cv::Vec4i templine = lines[i];
        if(templine[1] == templine[3])
        {
            filtered.push_back(templine);
            if(templine[1] >2000)
            {
                filtered_o1.push_back(templine);
            }else if(templine[1] >1000 && templine[1]<2000)
            {
                filtered_o2.push_back(templine);
            }else{
                filtered_o3.push_back(templine);
            }
        }
    }
    
    //regration lines
    regression_analysis(filtered_o1 , filtered_o1_k,filtered_o1_b);
    regression_analysis(filtered_o2 , filtered_o2_k,filtered_o2_b);
    regression_analysis(filtered_o3 , filtered_o3_k,filtered_o3_b);
    y1 = filtered_o2_b;
    y2 = filtered_o1_b;

}

void line_detecter::regression_analysis(std::vector<cv::Vec4i>  & number_pair , 
float & result_k,float & result_b)
{
    int i,j,k,n;
    std::cout<<"\nEnter the no. of data pairs to be entered:\n";        //To find the size of arrays
    //cin>>n;
    n = number_pair.size();
    double x[n],y[n],a,b;
    //std::cout<<"\nEnter the x-axis values:\n";                //Input x-values
    for (i=0;i<n;i++)
        x[i] = number_pair[i][0];
    //std::cout<<"\nEnter the y-axis values:\n";                //Input y-values
    for (i=0;i<n;i++)
        y[i] = number_pair[i][1];
    double xsum=0,x2sum=0,ysum=0,xysum=0;                //variables for sums/sigma of xi,yi,xi^2,xiyi etc
    for (i=0;i<n;i++)
    {
        xsum=xsum+x[i];                        //calculate sigma(xi)
        ysum=ysum+y[i];                        //calculate sigma(yi)
        x2sum=x2sum+pow(x[i],2);                //calculate sigma(x^2i)
        xysum=xysum+x[i]*y[i];                    //calculate sigma(xi*yi)
    }
    a=(n*xysum-xsum*ysum)/(n*x2sum-xsum*xsum);            //calculate slope
    b=(x2sum*ysum-xsum*xysum)/(x2sum*n-xsum*xsum);            //calculate intercept
    double y_fit[n];                        //an array to store the new fitted values of y    
    for (i=0;i<n;i++)
        y_fit[i]=a*x[i]+b;                    //to calculate y(fitted) at given x points
    std::cout<<"S.no"<<std::setw(5)<<"x"<<std::setw(19)<<"y(observed)"<<std::setw(19)<<"y(fitted)"<<std::endl;
    std::cout<<"-----------------------------------------------------------------\n";
    for (i=0;i<n;i++)
        std::cout<<i+1<<"."<<std::setw(8)<<x[i]<<std::setw(15)<<y[i]<<std::setw(18)<<y_fit[i]<<std::endl;//print a table of x,y(obs.) and y(fit.)    
    std::cout<<"\nThe linear fit line is of the form:\n\n"<<a<<"x + "<<b<<std::endl;
    result_k = a;
    result_b = b;
}


line_detecter::line_detecter()
{

}

line_detecter::~line_detecter()
{

}


// int main()
// {
//     src=imread("../image/8.jpg");
//     if(src.empty())
//     {
//         printf("could not load image ...");
//         return ;
//     }
//     imshow("src",src);
//    cvtColor(src,src,CV_BGR2GRAY);
//     //裁剪图像
//    // Rect rect=Rect(10,10,src.cols-20,src.rows-20);
//   //  src=src(rect);


//     //binary image
//     Mat binary,morhpImg;
//     //THRESH_BINARY_INV 返色
//     //二值化
//     threshold(src,binary,0,255,THRESH_BINARY_INV|THRESH_OTSU);

//     //morhpology形态学开操作
//     Mat kernel=getStructuringElement(MORPH_RECT,Size(20,1),Point(-1,-1));
//     morphologyEx(binary,morhpImg,MORPH_OPEN,kernel,Point(-1,-1));

//     imshow("output",morhpImg);
//     //膨胀操作
//     kernel=getStructuringElement(MORPH_RECT,Size(3,3),Point(-1,-1));
//     dilate(morhpImg,morhpImg,kernel);
//     imshow("output",morhpImg);

//     vector<Vec4i> lines;
    
//     HoughLinesP(morhpImg,lines,1,CV_PI/180.0,30,20.0,0);
//     Mat result=src.clone();
//     cvtColor(result,result,CV_GRAY2BGR);
//     for(int i=0;i<lines.size();i++)
//     {
//         Vec4i lin=lines[i];

//         line(result,Point(lin[0],lin[1]),Point(lin[2],lin[3]),Scalar(0,0,255),2,8,0);
//     }
// imshow("output",result);

// return 0;

//https://blog.csdn.net/qq_42503022/article/details/103618375
//https://blog.csdn.net/weixin_38341864/article/details/88825468